import React, { useEffect, useRef, useState } from "react";
import styles from "./SongManagement.module.css";
import { MusicHeader } from "../../components/MusicHeader/MusicHeader";
import {
  Button,
  Input,
  message,
  Modal,
  Form,
  Table,
  TableProps,
  UploadProps,
  Upload,
  GetProp,
  Select,
  Popconfirm,
  FormInstance,
} from "antd";
import {
  Result,
  songApi,
  songListApi,
  uploadApi,
} from "../../utils/backend/server";
import { Song } from "../../utils/domain/Song";
import {
  LoadingOutlined,
  PlusOutlined,
  UploadOutlined,
} from "@ant-design/icons";
import { useAppDispatch, useAppSelector } from "../../utils/store/hooks";
import {
  updateAllSongFileList,
  updateAllSongList,
} from "../../utils/store/songSlice";
import { Key } from "antd/es/table/interface";

const refreshAllSongFile = (pageNo: number = 1) => songApi.getAllSongs(pageNo);

const DelConfirm = (props: { getChosenList: () => Song["id"][] }) => {
  const dispatch = useAppDispatch();
  return (
    <div>
      <Popconfirm
        title="Delete the song?"
        description="Are you sure to delete all the songs?"
        onConfirm={() => {
          const list = props.getChosenList();
          if (list.length === 0) return;
          songApi.removeSongs(list).then((data) => {
            // console.log(data);
            message[data.success ? "success" : "error"](data.msg);

            refreshAllSongFile().then((data) => {
              dispatch(updateAllSongFileList(data));
            });
          });
        }}
        okText="Yes"
        cancelText="No"
      >
        <Button danger type="primary">
          delete
        </Button>
      </Popconfirm>
    </div>
  );
};

const AddToList = (props: { songs: Key[] }) => {
  const [show, setShow] = useState<boolean>(false);
  const rawList = useAppSelector((state) => state.song.allSongList);
  const [songList, setSongList] = useState<{ value: number; label: string }[]>(
    []
  );
  const dispatch = useAppDispatch();
  const [chosen, setChosen] = useState<number>(-1);
  useEffect(() => {
    songListApi.getAllListData().then((data) => {
      dispatch(updateAllSongList(data));
    });
  }, []);
  useEffect(() => {
    setSongList(rawList.map((val) => ({ value: val.id, label: val.listName })));
  }, [rawList]);
  return (
    <div>
      <Button
        onClick={() => {
          setShow(true);
        }}
      >
        add to list?
      </Button>
      <Modal
        open={show}
        onCancel={() => setShow(false)}
        onOk={() => {
          // console.log(chosen, props.songs);
          if (chosen === -1) {
            message.error("please choose song list!");
            return;
          }
          if (props.songs.length < 1) {
            message.error("please choose songs!");
            return;
          }
          songListApi
            .addSongsToList(chosen, props.songs.join(","))
            .then((data) => {
              message[data.success ? "success" : "error"](data.msg);
              if (data.success) {
                setShow(false);
              }
            });
        }}
      >
        <Select
          options={songList}
          style={{ width: 220 }}
          onChange={(val) => {
            setChosen(val);
          }}
        />
      </Modal>
    </div>
  );
};

const columns: TableProps<Song>["columns"] = [
  {
    title: "Name",
    dataIndex: "title",
    key: "title",
    render: (text, record: Song, index: number) => <a>{text}</a>,
  },
  {
    title: "author",
    dataIndex: "author",
    key: "author",
  },
  {
    title: "operation",
    key: "operation",
    render: (unknown: undefined, record: Song, seq: number) => {
      // const dispatch = useAppDispatch();

      return (
        <div className={styles.flex}>
          {/* <DelConfirm record={record} /> */}
          {/* <AddTo record={record} /> */}
        </div>
      );
    },
  },
];

export default () => {
  const [showAdd, setShowAdd] = useState<boolean>(false);
  const store = useAppSelector((state) => state.song.allSongFileList);
  const dispatch = useAppDispatch();
  const [selection, setSelection] = useState<Key[]>([]);

  const refresh = (pageNo = 1) => {
    refreshAllSongFile(pageNo).then((data) => {
      dispatch(updateAllSongFileList(data));
    });
  };

  useEffect(() => {
    refresh();
  }, []);

  return (
    <>
      <MusicHeader />
      <div>
        <Table
          pagination={{
            pageSize: 10,
            onChange(page, pageSize) {
              refresh(page);
            },
          }}
          rowSelection={{
            type: "checkbox",
            onChange(selectedRowKeys, selectedRows, info) {
              // console.log(selectedRowKeys);
              setSelection(selectedRowKeys);
            },
          }}
          columns={columns}
          dataSource={store}
          rowKey={(record) => record.id}
          footer={() => {
            return (
              <div className={styles.bet}>
                <div className={styles.flex}>
                  <AddToList songs={selection} />
                  <DelConfirm
                    getChosenList={() => {
                      return selection as unknown as number[];
                    }}
                  />
                </div>

                <Button
                  type="primary"
                  onClick={() => {
                    setShowAdd(true);
                  }}
                >
                  add new song
                </Button>
              </div>
            );
          }}
        />
      </div>

      <AddSong
        showAdd={showAdd}
        setShowAdd={setShowAdd}
        refresh={refresh}
        unique={new Date().valueOf()}
      />
    </>
  );
};
type FileType = Parameters<GetProp<UploadProps, "beforeUpload">>[0];
const getBase64 = (img: FileType, callback: (url: string) => void) => {
  const reader = new FileReader();
  reader.addEventListener("load", () => callback(reader.result as string));
  reader.readAsDataURL(img);
};

const uploadUrl = uploadApi.upload();

const norm = (e: any) => {
  console.log(e);

  if (Array.isArray(e)) return e;
  return e && e.fileList;
};

const AddSong = (props: {
  unique: string | number;
  showAdd: boolean;
  setShowAdd: (val: boolean) => void;
  refresh: () => void;
}) => {
  type FieldType = {
    songName?: string;
    thumbnail?: string;
    author?: string;
    genre?: string;
    album?: string;
    description?: string;
    songFile?: string;
    mv?: string;
  };

  const [form, setForm] = useState<FieldType>({});
  const [loading, setLoading] = useState(false);
  const [imageUrl, setImageUrl] = useState<string>();

  const formRef = useRef<null | any>();

  const handleChange: UploadProps<Result<string[]>>["onChange"] = (info) => {
    if (info.file.status === "uploading") {
      setLoading(true);
      return;
    }
    if (info.file.status === "done") {
      const url = info?.fileList?.[0]?.response?.data[0];
      setForm((form) => ({ ...form, thumbnail: url }));

      // Get this url from response in real world.
      getBase64(info.file.originFileObj as FileType, (url) => {
        setLoading(false);
        setImageUrl(url);
      });
    }
  };

  useEffect(() => {
    if (!props.showAdd && formRef.current) {
      formRef.current.resetFields();
      setForm({});
    }
  }, [props.showAdd]);

  return (
    <Modal
      open={props.showAdd}
      onCancel={() => props.setShowAdd(false)}
      onOk={() => {
        if (!form.songName) {
          message.error("please enter your song name!");
          return;
        }
        if (!form.songFile) {
          message.error("please choose your song file!");
          return;
        }
        // console.log(form, "form");
        songApi
          .addSong({
            id: -1,
            title: form.songName,
            thumbnail: form.thumbnail || "",
            author: form.author || "",
            genre: form.genre || "",
            album: form.album || "",
            description: form.description || "",
            duration: 0,
            mp3: form.songFile,
            mp4: form.mv,
          })
          .then((res) => {
            console.log(res);
            message[res.success ? "success" : "error"](res.msg);
            props.refresh();
            // refreshAllSongFile().then((data) =>
            //   dispatch(updateAllSongFileList(data))
            // );
          });
        props.setShowAdd(false);
      }}
    >
      <Form
        ref={formRef}
        name="basic"
        labelCol={{ span: 5 }}
        wrapperCol={{ span: 16 }}
        style={{ maxWidth: 600 }}
        initialValues={{ remember: false }}
        autoComplete="off"
      >
        <Form.Item<FieldType>
          label="song name"
          name="songName"
          rules={[{ required: true, message: "Please input your song name!" }]}
        >
          <Input
            key={props.unique}
            autoComplete="off"
            value={form.songName}
            onChange={(e) =>
              setForm((form) => ({ ...form, songName: e.target.value }))
            }
          />
        </Form.Item>

        <Form.Item<FieldType>
          label="thumbnail"
          name="thumbnail"
          getValueFromEvent={norm}
          valuePropName="fileList"
        >
          <Upload
            name="file"
            listType="picture-card"
            className="avatar-uploader"
            showUploadList={false}
            action={uploadUrl}
            onChange={handleChange}
          >
            {imageUrl ? (
              <img src={imageUrl} alt="avatar" style={{ width: "100%" }} />
            ) : (
              <button style={{ border: 0, background: "none" }} type="button">
                {loading ? <LoadingOutlined /> : <PlusOutlined />}
                <div style={{ marginTop: 8 }}>Upload</div>
              </button>
            )}
          </Upload>
        </Form.Item>
        <Form.Item<FieldType> label="author" name="author">
          <Input
            key={props.unique}
            autoComplete="off"
            value={form.author}
            onChange={(e) =>
              setForm((form) => ({ ...form, author: e.target.value }))
            }
          />
        </Form.Item>
        <Form.Item<FieldType> label="genre" name="genre">
          <Select
            style={{ width: 120 }}
            onChange={(e) => {
              setForm((form) => ({ ...form, genre: e }));
            }}
            options={[
              { value: "rap", label: "rap" },
              { value: "pop", label: "pop" },
              { value: "heavy_meatal", label: "heavy meatal" },
              { value: "rock", label: "rock" },
              { value: "classical", label: "classical" },
              { value: "lullaby", label: "lullaby" },
              { value: "country", label: "country" },
              { value: "jazz", label: "jazz" },
              { value: "electronic", label: "electronic" },
              { value: "blue", label: "blue" },
            ]}
          />
        </Form.Item>
        <Form.Item<FieldType> label="album" name="album">
          <Input
            key={props.unique}
            autoComplete="off"
            value={form.album}
            onChange={(e) =>
              setForm((form) => ({ ...form, album: e.target.value }))
            }
          />
        </Form.Item>
        <Form.Item<FieldType> label="description" name="description">
          <Input.TextArea
            key={props.unique}
            autoComplete="off"
            showCount
            maxLength={100}
            value={form.description}
            onChange={(e) =>
              setForm((form) => ({ ...form, description: e.target.value }))
            }
            placeholder="describe the song!"
            style={{ height: 120, resize: "none" }}
          />
        </Form.Item>

        <Form.Item<FieldType>
          getValueFromEvent={norm}
          valuePropName="fileList"
          label="song file"
          name="songFile"
        >
          <Upload
            name="file"
            action={uploadUrl}
            onChange={(info) => {
              if (info.file.status === "done") {
                const url = info.fileList[0].response.data[0];
                setForm((form) => ({ ...form, songFile: url }));
              }
            }}
          >
            <Button icon={<UploadOutlined />}>Click to Upload</Button>
          </Upload>
        </Form.Item>
        <Form.Item<FieldType>
          getValueFromEvent={norm}
          valuePropName="fileList"
          label="mv file"
          name="mv"
        >
          <Upload
            name="file"
            action={uploadUrl}
            onChange={(info) => {
              if (info.file.status === "done") {
                const url = info.fileList[0].response.data[0];
                setForm((form) => ({ ...form, mv: url }));
              }
            }}
          >
            <Button icon={<UploadOutlined />}>Click to Upload</Button>
          </Upload>
        </Form.Item>
      </Form>
    </Modal>
  );
};
